package com.xiaoyang.forum.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.xiaoyang.forum.common.code.Result;
import com.xiaoyang.forum.common.code.ResultCode;
import com.xiaoyang.forum.common.exception.ApplicationException;
import com.xiaoyang.forum.common.util.MailUtil;
import com.xiaoyang.forum.domain.dto.ArticleDTO;
import com.xiaoyang.forum.domain.dto.ArticleListDTO;
import com.xiaoyang.forum.domain.dto.ArticleModifyDTO;
import com.xiaoyang.forum.domain.pojo.Article;
import com.xiaoyang.forum.domain.pojo.ArticleLike;
import com.xiaoyang.forum.domain.pojo.Board;
import com.xiaoyang.forum.domain.pojo.User;
import com.xiaoyang.forum.domain.vo.*;
import com.xiaoyang.forum.mapper.ArticleLikeMapper;
import com.xiaoyang.forum.mapper.ArticleMapper;
import com.xiaoyang.forum.mapper.BoardMapper;
import com.xiaoyang.forum.mapper.UserMapper;
import com.xiaoyang.forum.service.IArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * @author XiaoYang
 * @since 2025-08-14
 */
@Slf4j
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements IArticleService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private BoardMapper boardMapper;

    @Autowired
    private ArticleLikeMapper articleLikeMapper;

    @Autowired
    private MailUtil mailUtil;

    /**
     * 创建文章
     * @param userId
     * @param articleDTO
     */
    @Override
    public ArticleUserNameVO create(Integer userId, ArticleDTO articleDTO) {

        // 2. 校验版块是否存在
        Board board = boardMapper.selectById(articleDTO.getBoardId());
        if (board == null) {
            // 版块不存在
            log.info("版块不存在" + articleDTO.getBoardId());
            throw new ApplicationException(Result.failed(ResultCode.FAILED_NOT_EXISTS));
        }

        // 1. 根据userId查询用户
        User user = userMapper.selectById(userId);
        if (user.getState() == 1) {
            // 用户已被禁言
            log.info("用户已被禁言" + userId);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_USER_BANNED));
        }

        // 2. 创建文章
        Article article = new Article();
        article.setUserId(Long.valueOf(userId)); // 用户id
        article.setBoardId(articleDTO.getBoardId()); // 版块id
        article.setTitle(articleDTO.getTitle()); // 标题
        article.setContent(articleDTO.getContent()); // 内容
        article.setVisitCount(0); // 访问次数
        article.setReplyCount(0); // 回复次数
        article.setLikeCount(0); // 点赞次数
        article.setState(0); // 状态
        article.setCreateTime(LocalDateTime.now());
        article.setUpdateTime(LocalDateTime.now());
        articleMapper.insert(article);
        log.info("创建文章成功" + article.getId());

        // 更新用户文章数
        int row = user.getArticleCount() + 1;
        user.setArticleCount(row);
        // 3. 更新数据库数据
        userMapper.updateById(user);
        log.info("更新用户文章数成功" + row);

        // 更新版块文章数
        // 1. 更新版块文章数
        row = board.getArticleCount() + 1;
        board.setArticleCount(row);
        // 2. 更新数据库数据
        boardMapper.updateById(board);
        log.info("更新版块文章数成功" + row);

        ArticleUserNameVO articleUserNameVO = new ArticleUserNameVO();
        articleUserNameVO.setUsername(user.getUsername());
        articleUserNameVO.setBoardId(article.getBoardId());
        articleUserNameVO.setTitle(article.getTitle());
        articleUserNameVO.setContent(article.getContent());

//         todo 通知管理员审核
        log.info("通知管理员审核");
        mailUtil.sendSampleMail("17823506445@163.com", "新文章审核", "新文章审核");
        return articleUserNameVO;
    }

    /**
     * 查询全部文章列表
     * @param ArticleListDTO
     * @return
     */
    @Override
    public List<ArticleListVO> selectAll(ArticleListDTO ArticleListDTO) {
        log.info("获取全部文章列表");
        PageHelper.startPage(ArticleListDTO.getPageNum(), ArticleListDTO.getPageSize());
        return articleMapper.selectAll(ArticleListDTO.getPageNum(), ArticleListDTO.getPageSize());
    }

    /**
     * 根据id查询文章列表
     * @param articleListDTO
     * @return
     */
    @Override
    public List<ArticleListVO> selectById(ArticleListDTO articleListDTO) {
        log.info("根据id查询文章列表");
        // 1. 校验版块是否存在
        Board board = boardMapper.selectById(articleListDTO.getBoardId());
        if (board == null) {
            // 版块不存在
            log.info("版块不存在" + articleListDTO.getBoardId());
            throw new ApplicationException(Result.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        PageHelper.startPage(articleListDTO.getPageNum(), articleListDTO.getPageSize());
        return articleMapper.selectByBoardId(articleListDTO.getPageNum(), articleListDTO.getPageSize(), articleListDTO.getBoardId());
    }

    /**
     * 获取文章详情
     * @param id
     * @return
     */
    @Override
    public ArticleUserVO getDetails(Long id) {
        // 1. 校验文章是否存在
        Article article = getArticle(id);
        // 2. 获取文章详情
        ArticleUserVO articleUserVO = articleMapper.selectDetailById(id);

        // 3. 访问次数加1
        // 扩展: redis缓存
        article.setVisitCount(article.getVisitCount() + 1);
        articleMapper.updateById(article);
        log.info("访问次数加1" + article.getVisitCount());

        // 4. 根据版块id 获取版块名称
        Board board = boardMapper.selectById(article.getBoardId());
        articleUserVO.setBoardName(board.getName());

        return articleUserVO;
    }

    /**
     * 修改文章
     * @param userId
     * @param articleModifyDTO
     * @return
     */
    @Override
    public ArticleModifyVO modify(long userId, ArticleModifyDTO articleModifyDTO) {
        // 1. 校验文章是否存在
        Article article = getArticle(articleModifyDTO.getId());
        if (article.getUserId() != userId) {
            // 用户没有权限修改文章
            log.info("用户没有权限修改文章" + userId);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_USER_NO_PERMISSION));
        }

        article.setTitle(articleModifyDTO.getTitle());
        article.setContent(articleModifyDTO.getContent());
        article.setUpdateTime(LocalDateTime.now());
        articleMapper.updateById(article);
        log.info("修改文章成功" + article.getId());

        ArticleModifyVO articleModifyVO = new ArticleModifyVO();
        articleModifyVO.setId(article.getId());
        articleModifyVO.setTitle(article.getTitle());
        articleModifyVO.setContent(article.getContent());
        return articleModifyVO;
    }

    /**
     * 删除文章
     * @param articleId 文章id
     * @param userId    用户id
     * @return
     */
    @Override
    public ArticleVO deleteById(Long articleId, long userId) {
        // 1. 校验文章是否存在
        Article article = getArticle(articleId);

        if (article.getUserId() != userId) {
            // 用户没有权限删除文章
            log.info("用户没有权限删除文章" + userId);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_USER_NO_PERMISSION));
        }

        // 2. 删除文章
        articleMapper.deleteById(articleId);
        // 3. 更新版块文章数
        Board board = boardMapper.selectById(article.getBoardId());
        board.setArticleCount(board.getArticleCount() - 1);
        boardMapper.updateById(board);
        log.info("更新版块文章数成功" + board.getArticleCount());

        ArticleVO articleVO = new ArticleVO();
        articleVO.setId(articleId);
        articleVO.setBoardId(article.getBoardId());
        articleVO.setUserId(article.getUserId());
        articleVO.setTitle(article.getTitle());
        articleVO.setContent(article.getContent());
        articleVO.setVisitCount(article.getVisitCount());
        articleVO.setReplyCount(articleVO.getReplyCount());
        articleVO.setLikeCount(articleVO.getLikeCount());

        return articleVO;
    }

    /**
     * TA的精选
     * @return
     */
    @Override
    public List<ArticleRelatedVO> getUserChoiceness(Long userId) {
        log.info("TA的精选");
        User user = userMapper.selectById(userId);
        if (user == null) {
            // 用户不存在
            log.info("用户不存在" + userId);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }
        return articleMapper.getUserChoiceness(userId);
    }

    /**
     * 点赞
     * @param userId
     * @param articleId
     */
    @Override
    public ArticleLikeVO thumbsUp(long userId, Long articleId) {
        // 1. 校验文章是否存在
        Article article = getArticle(articleId);

        // 2. 根据用户id和文章id查询点赞记录
        ArticleLike articleLike = articleLikeMapper.selectOne(new QueryWrapper<ArticleLike>()
                .eq("user_id", userId).eq("article_id", articleId));
        if (articleLike != null) {
            // 已点赞 取消点赞
            log.info("取消点赞:" + userId + "帖子:" + articleId);
            articleLikeMapper.deleteById(articleLike.getId());

            // 3. 点赞数减1
            article.setLikeCount(article.getLikeCount() - 1);
            articleMapper.updateById(article);
        } else {
            // 未点赞 点赞
            log.info("点赞:" + userId + "帖子:" + articleId);
            articleLike = new ArticleLike();
            articleLike.setUserId(userId);
            articleLike.setArticleId(articleId);
            articleLike.setLikeCount(1);
            articleLike.setCreateTime(LocalDateTime.now());
            articleLike.setUpdateTime(LocalDateTime.now());
            articleLikeMapper.insert(articleLike);

            // 3. 点赞数加1
            article.setLikeCount(article.getLikeCount() + 1);
            articleMapper.updateById(article);
        }

        ArticleLikeVO articleLikeVO = new ArticleLikeVO();
        articleLikeVO.setTitle(article.getTitle());
        articleLikeVO.setContent(article.getContent());
        articleLikeVO.setVisitCount(article.getVisitCount());
        articleLikeVO.setReplyCount(article.getReplyCount());
        articleLikeVO.setLikeCount(article.getLikeCount());
        return articleLikeVO;
    }

    /**
     * 获取用户点赞列表
     * @param userId
     * @return
     */
    @Override
    public List<ArticleUserLikeListVO> getUserThumbsUpList(Long userId) {
        log.info("获取用户点赞列表");
        User user = userMapper.selectById(userId);
        if (user == null) {
            // 用户不存在
            log.info("用户不存在" + userId);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_USER_NOT_EXISTS));
        }

        return articleMapper.getUserThumbsUpList(userId);
    }

    /**
     * 校验文章是否存在
     * @param id 文章id
     * @return
     */
    private Article getArticle(Long id) {
        // 1. 校验文章是否存在
        Article article = articleMapper.selectById(id);
        if (article == null) {
            // 文章不存在
            log.info("文章不存在" + id);
            throw new ApplicationException(Result.failed(ResultCode.FAILED_NOT_EXISTS));
        }
        return article;
    }
}
